package com.catcoin.finance.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.catcoin.finance.mapper.AccountMapper;
import com.catcoin.finance.mapper.LogBlanceccMapper;
import com.catcoin.finance.model.*;
import com.catcoin.finance.mapper.LogPurseAccrualMapper;
import com.catcoin.finance.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.catcoin.finance.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 理财钱包利息流水 服务实现类
 * </p>
 *
 * @author caody
 * @since 2018-09-03
 */
@Service
public class LogPurseAccrualServiceImpl extends ServiceImpl<LogPurseAccrualMapper, LogPurseAccrual> implements ILogPurseAccrualService {
    @Autowired
    private ILogPurseCorpusService iLogPurseCorpusService;
    @Autowired
    private ILogBlanceccService iLogBlanceccService;
    @Autowired
    private ILogMailccService iLogMailccService;
    @Autowired
    private ISysConfigsService iSysConfigsService;
    @Autowired
    private ToolfeignInterface toolfeignInterface;
    @Autowired
    private IAccountService iAccountService;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private IMoneyccService iMoneyccService;
    @Autowired
    private LogBlanceccMapper logBlanceccMapper;
    @Autowired
    private LogPurseAccrualMapper logPurseAccrualMapper;
    /**
     * 每日最高提出额度(本金百分比)
     */
    private static final String highestLimit = "highestLimit";
    /**
     *  提币到强制消费(百分比)
     */
    private static final String withdrawToForce = "withdrawToForce";
    /**
     * 提币到余额(百分比)
     */
    private static final String withdrawToBlancecc = "withdrawToBlancecc";

    private BigDecimal accmailcc;
    private BigDecimal accblancecc;

    @Override
    @Transactional
    public Map<String, String> withdrawPurse(Integer userId, String withdrawSum,Integer type) {
        Map<String,String> result = new HashMap<String,String>();
        //用户信息
        Account account = iAccountService.selectOne(new EntityWrapper<Account>().eq("userId", userId));
        //理财钱包当前可用利息总和
        BigDecimal ieterestcc = account.getIeterestcc();
        //本金清零总利息(可全部提币)
        BigDecimal moneyToZeroIt = account.getMoneyToZeroIt();
        //本金未清零总利息(按总可用本金百分比提币)
        BigDecimal moneyNoZeroIt = account.getMoneyNoZeroIt();
        //用户输入提币数量
        BigDecimal withdrawSumTotal = new BigDecimal(withdrawSum);
        //用户当日最高提币数量
        BigDecimal highest = new BigDecimal("0");
        //提币到强制消费配置信息（后台可控）
        SysConfigs mailcc = iSysConfigsService.selectOne(new EntityWrapper<SysConfigs>().eq("fieldCode", withdrawToForce));
        //提币到消费百分比
        BigDecimal mailccPercentage = new BigDecimal(mailcc.getFieldValue()).divide(new BigDecimal("100"));
        //提币到强制消费数量
        BigDecimal mailccVal = withdrawSumTotal.multiply(mailccPercentage);
        //提币到余额消费配置信息(后台可控）
        SysConfigs blancecc = iSysConfigsService.selectOne(new EntityWrapper<SysConfigs>().eq("fieldCode", withdrawToBlancecc));
        //提币到猫币余额百分比
        BigDecimal blanceccPercentage =  new BigDecimal(blancecc.getFieldValue()).divide(new BigDecimal("100"));
        //提币到猫币余额数量
        BigDecimal blanceccVal = withdrawSumTotal.multiply(blanceccPercentage);
        //用户可用利息
        BigDecimal accIeterestcc = account.getIeterestcc();
        BigDecimal noZeroIt = account.getMoneyNoZeroIt();
        BigDecimal toZeroIt = account.getMoneyToZeroIt();
        accmailcc = account.getMailcc();
        accblancecc = account.getBlancecc();
        Boolean flag = false;
        BigDecimal subtractResult = withdrawSumTotal;
        //type  0本金清零的总利息(可全部提币)
        if(type == 0){
            //用户当日最高提币数量(本金清零总利息可全部提币)
            highest = account.getMoneyToZeroIt();
            if(highest.compareTo(new BigDecimal("0"))==0) {
                //本金清零总利息(可全部提币)为零
                result.put("ERROR", "当前可用利息为零");
                return result;
            }
            //根据创建时间升序查询用户Moneycc
            List<Moneycc> moneyccList = iMoneyccService.selectList(
                    new EntityWrapper<Moneycc>()
                            .eq("userId", userId)
                            .eq("status",0)
                            .orderBy("createTime"));
            if (moneyccList.isEmpty()){
                result.put("ERROR","该用户没用可用利息");
                return result;
            }
            if(highest.compareTo(withdrawSumTotal)==-1) {
                result.put("ERROR","利息不足，请重新输入");
                return result;
            }
            for (Moneycc moneycc1:moneyccList) {
                //此笔理财本金当前剩余利息
                BigDecimal nowAccrual =  moneycc1.getNowAccrual();
                if (nowAccrual.compareTo(new BigDecimal("0"))==0)
                    continue;
                //当前moneycc记录可用利息大于等于用户输入
                if (nowAccrual.compareTo(subtractResult)!=-1){
                    BigDecimal  mailccVal1 = subtractResult.multiply(mailccPercentage);
                    BigDecimal  blanceccVal1 = subtractResult.multiply(blanceccPercentage);
                    //理财利息流水（理财利息到商城消费减少流水）
                    Boolean lpaResult = this.insertLogPurseAccrual(userId, accIeterestcc,mailccVal1, "2",moneycc1, -1, "理财钱包提币到消费", 2);
                    //消费流水（消费增加流水）
                    Boolean lmResult = iLogMailccService.insertLogMailcc(userId,moneycc1,accmailcc, mailccVal1, "3", 1, "每天提币获得", 3);
                    //理财利息流水（理财利息到猫币余额减少流水）
                    Boolean lpaFlag = this.insertLogPurseAccrual(userId,accIeterestcc.subtract(mailccVal1),blanceccVal1,"3",moneycc1,-1,"理财钱包提币到猫币余额",3);
                    //猫币余额流水（猫币余额增加流水）
                    Boolean lbResult = iLogBlanceccService.insertLogBlancecc2(userId,moneycc1.getId(),accblancecc, blanceccVal1, "3", 1, "每天提币获得", 3);
                    //减少理财钱包当前可用利息总和    增加商城可消费余额     增加用户猫币余额    减少本金未清零总利息(按总可用本金百分比提币)
                    Boolean accountesult = this.updateAccountDB(userId, withdrawSumTotal, mailccVal, blanceccVal);
                    //保存moneycc
                    moneycc1.setNowAccrual(moneycc1.getNowAccrual().subtract(subtractResult));
                    Boolean moneyccResult = iMoneyccService.updateById(moneycc1);
                    if(lpaResult && lmResult && lpaFlag && lbResult && accountesult && moneyccResult) {
                        flag = true;
                        break;
                    }
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    result.put("ERROR","提币失败");
                    return result;
                }
                //当前moneycc记录可用利息小于用户输入
                if (nowAccrual.compareTo(subtractResult)==-1) {
                    Boolean aBoolean = this.forEachUpdate(userId, accIeterestcc, nowAccrual, mailccPercentage, blanceccPercentage, moneycc1);
                    if (!aBoolean) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        result.put("ERROR", "提币失败");
                        return result;
                    }
                    accIeterestcc = accIeterestcc.subtract(nowAccrual);
                    subtractResult = subtractResult.subtract(nowAccrual);
                    continue;
                }
            }
        }
        //1提本金未清零总利息(按总可用本金百分比提币)
        if(type == 1){
            //用户当日最高提币数量
            BigDecimal moneycc = iLogPurseCorpusService.highestLimit(userId);
            if(moneycc == null){
                //理财钱包当前可用利息总和为零
                result.put("ERROR","当前可用本金为零");
                return result;
            }
            //用户当日已提币数量(猫币提币流水)
            BigDecimal mailccValue = iLogMailccService.selectMailccCountByUserId(userId);
            BigDecimal blanceccValue = logBlanceccMapper.selectBlanceccCountByUserId(userId);
            BigDecimal todayTotal = new BigDecimal("0");
            if(mailccValue != null && blanceccValue != null){
                todayTotal = mailccValue.add(blanceccValue);
            }
            if(todayTotal.compareTo(new BigDecimal("0"))!=0){
                //用户当日剩余可提币数量
                BigDecimal withdrawSumNow = moneycc.subtract(todayTotal);
                if (withdrawSumTotal.compareTo(withdrawSumNow)==1){
                    result.put("ERROR","当日已经提币数量为:"+todayTotal.setScale(6,BigDecimal.ROUND_HALF_EVEN)+",当日剩余可提币数量为:"+withdrawSumNow.setScale(6,BigDecimal.ROUND_HALF_EVEN));
                    return result;
                }
            }
            if (withdrawSumTotal.compareTo(moneycc)==1){
                result.put("ERROR","请重新填写提币数量"+",当日最大可提币总数量为:"+moneycc.setScale(6,BigDecimal.ROUND_HALF_EVEN));
                return result;
            }
            if(withdrawSumTotal.compareTo(noZeroIt)==1){
                result.put("ERROR","请重新填写提币数量"+",利息不足,当前可用利息数量为:"+noZeroIt.setScale(6,BigDecimal.ROUND_HALF_EVEN));
                return result;
            }
            //根据创建时间升序查询用户Moneycc
            List<Moneycc> moneyccList = iMoneyccService.selectList(
                    new EntityWrapper<Moneycc>()
                            .eq("userId", userId)
                            .eq("status",1)
                            .orderBy("createTime"));
            if (moneyccList.isEmpty()){
                result.put("ERROR","该用户没有本金可产生利息");
                return result;
            }
            for (Moneycc moneycc1:moneyccList) {
                //此笔理财本金当前剩余利息
                BigDecimal nowAccrual =  moneycc1.getNowAccrual();
                if (nowAccrual.compareTo(new BigDecimal("0"))==0)
                    continue;
                //当前moneycc记录可用利息大于等于用户输入
                if (nowAccrual.compareTo(subtractResult)!=-1){
                     //mailccVal = subtractResult.multiply(mailccPercentage);
                    //BigDecimal mailccVal1 = withdrawSumTotal.multiply(mailccPercentage);
                    BigDecimal  mailccVal1 = subtractResult.multiply(mailccPercentage);
                    BigDecimal  blanceccVal1 = subtractResult.multiply(blanceccPercentage);
                    //理财利息流水（理财利息到商城消费减少流水）
                    Boolean lpaResult = this.insertLogPurseAccrual(userId, accIeterestcc,mailccVal1, "2",moneycc1, -1, "理财钱包提币到消费", 2);
                    //消费流水（消费增加流水）
                    Boolean lmResult = iLogMailccService.insertLogMailcc(userId,moneycc1,accmailcc, mailccVal1, "3", 1, "每天提币获得", 3);
                    //理财利息流水（理财利息到猫币余额减少流水）
                    Boolean lpaFlag = this.insertLogPurseAccrual(userId,accIeterestcc.subtract(mailccVal1),blanceccVal1,"3",moneycc1,-1,"理财钱包提币到猫币余额",3);
                    //猫币余额流水（猫币余额增加流水）
                    Boolean lbResult = iLogBlanceccService.insertLogBlancecc2(userId,moneycc1.getId(),accblancecc, blanceccVal1, "3", 1, "每天提币获得", 3);
                    //减少理财钱包当前可用利息总和    增加商城可消费余额     增加用户猫币余额    减少本金未清零总利息(按总可用本金百分比提币)
                    Boolean accountesult = this.updateAccountDB(userId, withdrawSumTotal, mailccVal, blanceccVal);
                    //保存moneycc
                    moneycc1.setNowAccrual(moneycc1.getNowAccrual().subtract(subtractResult));
                    Boolean moneyccResult = iMoneyccService.updateById(moneycc1);
                    if(lpaResult && lmResult && lpaFlag && lbResult && accountesult && moneyccResult) {
                        flag = true;
                        break;
                    }
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    result.put("ERROR","提币失败");
                    return result;
                }
                //当前moneycc记录可用利息小于用户输入
                if (nowAccrual.compareTo(subtractResult)==-1){
                    Boolean aBoolean = this.forEachUpdate(userId, accIeterestcc,nowAccrual, mailccPercentage, blanceccPercentage, moneycc1);
                    //accIeterestcc = accIeterestcc.add(nowAccrual);
                    if (!aBoolean){
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        result.put("ERROR","提币失败");
                        return result;
                    }
                    accIeterestcc = accIeterestcc.subtract(nowAccrual);//总利息从里边减?
                    subtractResult = subtractResult.subtract(nowAccrual);
                    continue;
                }
            }
        }
        if (flag){
            //修改account
            if (type==1){
                account.setIeterestcc(account.getIeterestcc().subtract(withdrawSumTotal));
                account.setMoneyNoZeroIt(account.getMoneyNoZeroIt().subtract(withdrawSumTotal));
                account.setBlancecc(account.getBlancecc().add(blanceccVal));
                account.setMailcc(account.getMailcc().add(mailccVal));
                accountMapper.updateById(account);
            }
            if (type==0){
                account.setIeterestcc(account.getIeterestcc().subtract(withdrawSumTotal));
                account.setMoneyToZeroIt(account.getMoneyToZeroIt().subtract(withdrawSumTotal));
                account.setBlancecc(account.getBlancecc().add(blanceccVal));
                account.setMailcc(account.getMailcc().add(mailccVal));
                accountMapper.updateById(account);
            }
            //第三方修改结果
            String operate=null;
            //第三方修改
            //获取交易所userId
            AccountDTO accountDTO = accountMapper.selectAccountDtoByUserId(userId);
            String userIdResult = toolfeignInterface.register(accountDTO.getUserPhone());
            if(!"getRegisterERROR".equals(userIdResult)){
                JSONObject jsonObject = JSONObject.parseObject(userIdResult);
                if("true".equals(jsonObject.get("isSuc").toString())){
                    JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.get("datas").toString());
                    String userID = jsonObject1.get("userID").toString();
                    //operate = toolfeignInterface.operate(userID, "17", "1", String.valueOf(blanceccVal));
                    operate = toolfeignInterface.operate("305312", "17", "1", String.valueOf(blanceccVal));
                }
            }
            if(null == operate){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                result.put("ERROR","提币失败,请稍后重试");
                return result;
            }
            if("getOperateERROR".equals(operate)){
                result.put("ERROR","交易所猫币余额充值失败，请稍后重试");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return result;
            }
            JSONObject jsonObjectOperate = JSONObject.parseObject(operate);
            if("success".equals(jsonObjectOperate.get("des").toString())){
                result.put("SUCCESS","提币成功");
                return result;
            }
        }
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        result.put("ERROR","提币失败");
        return result;
    }

    public Boolean forEachUpdate(Integer userId,BigDecimal accIeterestcc,BigDecimal nowAccrual,BigDecimal mailccPercentage,BigDecimal blanceccPercentage,Moneycc moneycc1){
        Boolean flag = false;
        //理财利息流水（理财利息到商城消费减少流水）accmailcc accblancecc
        Boolean lpaResult = this.insertLogPurseAccrual(userId,accIeterestcc,nowAccrual.multiply(mailccPercentage), "2",moneycc1, -1, "理财钱包提币到消费", 2);
        //理财利息流水（理财利息到猫币余额减少流水）
        Boolean lpaFlag = this.insertLogPurseAccrual(userId,accIeterestcc.subtract(nowAccrual.multiply(mailccPercentage)),nowAccrual.multiply(blanceccPercentage),"3",moneycc1,-1,"理财钱包提币到猫币余额",3);
        //消费流水（消费增加流水）?
        //Boolean lmResult = iLogMailccService.insertLogMailcc(userId, nowAccrual.multiply(mailccPercentage), "3", 1, "理财钱包提币到消费", 3);
        Boolean lmResult = iLogMailccService.insertLogMailcc(userId,moneycc1,accmailcc, nowAccrual.multiply(mailccPercentage), "3", 1, "理财钱包提币到消费", 3);
        //猫币余额流水（猫币余额增加流水）?
        //Boolean lbResult = iLogBlanceccService.insertLogBlancecc2(userId,moneycc1.getId(),accIeterestcc.add(nowAccrual.multiply(mailccPercentage)), nowAccrual.multiply(blanceccPercentage), "3", 1, "理财钱包提币到猫币余额", 3);
        Boolean lbResult = iLogBlanceccService.insertLogBlancecc2(userId,moneycc1.getId(),accblancecc, nowAccrual.multiply(blanceccPercentage), "3", 1, "理财钱包提币到猫币余额", 3);
        accmailcc = accmailcc.add( nowAccrual.multiply(mailccPercentage));
        accblancecc = accblancecc.add( nowAccrual.multiply(blanceccPercentage));
        //减少理财钱包当前可用利息总和    增加商城可消费余额     增加用户猫币余额    减少本金未清零总利息(按总可用本金百分比提币)
        Boolean accountesult = this.updateAccountDB1(userId, nowAccrual, nowAccrual.multiply(mailccPercentage), nowAccrual.multiply(blanceccPercentage));
        //保存moneycc
        moneycc1.setNowAccrual(new BigDecimal("0"));
        Boolean moneyccResult = iMoneyccService.updateById(moneycc1);
        if(lpaResult && lmResult && lpaFlag && lbResult && accountesult && moneyccResult)
            flag = true;
        return flag;
    }

    /**
     * 生成理财钱包利息流水
     * @param userId
     * @param preValue  操作前的数量
     * @param purseCorpus  变化的数量
     * @param sign   2理财钱包提币到消费   3理财钱包提币到猫币余额
     * @param purseAccrualType  流水标志 -1减少 1增加
     * @param setRemark 备注 理财钱包提币到消费   理财钱包提币猫币到余额
     * @param type 类型 2理财钱包提币到消费  3理财钱包提币到猫币余额
     * @return
     */
    public Boolean insertLogPurseAccrual(Integer userId,BigDecimal preValue,BigDecimal purseCorpus,String sign,Moneycc moneycc,Integer purseAccrualType,String setRemark,Integer type){
        LogPurseAccrual logPurseAccrual = new LogPurseAccrual();
        logPurseAccrual.setUserId(userId);
        logPurseAccrual.setFromId(userId);
        logPurseAccrual.setOrderNo(StringUtils.getOrderIdByTime(sign));
        logPurseAccrual.setMoneyccId(moneycc.getId());
        logPurseAccrual.setPrePurseAccrual(preValue);
        logPurseAccrual.setPurseAccrual(purseCorpus);
        logPurseAccrual.setPurseAccrualType(purseAccrualType);
        logPurseAccrual.setRemark(setRemark);
        logPurseAccrual.setDataFlag(1);
        logPurseAccrual.setCreateTime(new Date());
        logPurseAccrual.setType(type);
        return this.insert(logPurseAccrual);
    }

    /**
     * 减少用户理财利息 增加用户消费金额 增加用户猫币余额
     * @param userId
     * @param ieterestcc  理财余额
     * @param mailcc  商城可消费余额
     * @param blancecc  猫币余额
     * @return
     */
    public boolean updateAccountDB(Integer userId,BigDecimal ieterestcc,BigDecimal mailcc,BigDecimal blancecc){
        Account account = iAccountService.selectOne(new EntityWrapper<Account>().eq("userId", userId));
        account.setIeterestcc(account.getIeterestcc().subtract(ieterestcc));
        account.setMailcc(account.getMailcc().add(mailcc));
        account.setBlancecc(account.getBlancecc().add(blancecc));
        account.setMoneyNoZeroIt(account.getMoneyNoZeroIt().subtract(ieterestcc));
        return  iAccountService.update(account, new EntityWrapper<Account>().eq("userId", userId));
    }

    public boolean updateAccountDB1(Integer userId,BigDecimal ieterestcc,BigDecimal mailcc,BigDecimal blancecc){
        Account account = iAccountService.selectOne(new EntityWrapper<Account>().eq("userId", userId));//?
        account.setIeterestcc(account.getIeterestcc().subtract(ieterestcc));
        account.setMailcc(account.getMailcc().add(mailcc));
        account.setBlancecc(account.getBlancecc().add(blancecc));
        account.setMoneyToZeroIt(account.getMoneyToZeroIt().subtract(ieterestcc));
        return  iAccountService.update(account, new EntityWrapper<Account>().eq("userId", userId));
    }


    @Override
    public Map<String, Object> queryPurseAccrualLog(Integer userId) {
        Map<String,Object> purseAccrualMap = new HashMap<String,Object>();
        //理财钱包提币到消费流水
        List<Map<String,String>> logAccrualsMailcc = logPurseAccrualMapper.queryPurseAccrualLog(userId, -1, 2);
        //理财钱包提币到猫币余额流水
        List<Map<String,String>> logPurseAccrualsToBlancecc = logPurseAccrualMapper.queryPurseAccrualLog(userId, -1, 3);
        //理财钱包本金生成理财钱包利息流水
        List<Map<String,String>> logCorpusCreateAccruals = logPurseAccrualMapper.queryPurseAccrualLog(userId, 1, 4);
        purseAccrualMap.put("理财钱包提币到消费流水",logAccrualsMailcc);
        purseAccrualMap.put("理财钱包提币到猫币余额流水",logPurseAccrualsToBlancecc);
        purseAccrualMap.put("理财钱包本金生成理财钱包利息流水",logCorpusCreateAccruals);
        return purseAccrualMap;
    }
}
